﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.ShprossesBuilder.Modelling;
using System.Drawing;
using ITAP.ShprossesBuilder.Modelling.Components;
using ITAP.Core.Modelling;

namespace ITAP.ShprossesBuilder.Manipulation
{
    public class CommandEditorChangeShprossLength : IModelComponentCommand
    {
        private ModelControl modelControl;
        private Model model;
        private RectangleF activeModelBoundingBox;
        private MouseManagerEvent mouseEvent;
        private Point mouseDownPoint;
        private Point mouseMovePoint;
        private Point mouseUpPoint;
        private List<Shpross> startShprosses;
        private List<Shpross> endShprosses;
        public CommandEditorChangeShprossLength(ModelControl modelControl)
        {
            this.modelControl = modelControl;
            this.startShprosses = new List<Shpross>();
            this.endShprosses = new List<Shpross>();
            this.componentsForProcessing = new List<IComponent>();
        }

        #region IModelComponentCommand Members

        private List<IComponent> componentsForProcessing;

        public List<ITAP.ShprossesBuilder.Modelling.Components.IComponent> ComponentsForProcessing
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        #endregion

        #region IModelControlCommand Members

        public MouseManagerEvent MouseEvent
        {
            get
            {
                return mouseEvent;
            }
            set
            {
                mouseEvent = value;
            }
        }

        public ModelControl ModelControl
        {
            get
            {
                return modelControl;
            }
            set
            {
                modelControl = value;
            }
        }

        public System.Drawing.Point MouseDownPoint
        {
            get
            {
                return mouseDownPoint;
            }
            set
            {
                mouseDownPoint = value;
            }
        }

        public System.Drawing.Point MouseUpPoint
        {
            get
            {
                return mouseUpPoint;
            }
            set
            {
                mouseUpPoint = value;
            }
        }

        public System.Drawing.Point MouseMovePoint
        {
            get
            {
                return mouseMovePoint;
            }
            set
            {
                mouseMovePoint = value;
            }
        }

        public bool ExecuteImmediately
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        #endregion

   //     private ModelPoint startExecutePoint;
    //    private ModelPoint executePoint;
     //   private ModelPoint endExecutePoint;

        private Point prevPoint;

        #region ICommand Members

        public void StartExecute()
        {
            this.startShprosses.Clear();
            this.endShprosses.Clear();
          //  this.undoModelContainer = (ModelContainer)this.modelControl.ModelContainer.Clone();
            ModelCell activeCell = this.modelControl.ModelContainer.ActiveCell as ModelCell;
            if (activeCell != null)
                this.activeModelBoundingBox = activeCell.Model.BoundingBox;
            else
                this.activeModelBoundingBox = RectangleF.Empty;

            componentsForProcessing.Clear();
            foreach (IComponent innerComponent in this.modelControl.ModelContainer.AllInnerComponents)
            {
                
                if (innerComponent.Selected && innerComponent is Shpross)
                {
                    componentsForProcessing.Add(innerComponent);
                }
            }
            prevPoint = mouseDownPoint;

            foreach (Shpross shpross in componentsForProcessing)
                this.startShprosses.Add(shpross.Copy() as Shpross);
            if(activeCell != null)
                this.model = activeCell.Model;

        }

        public void Execute()
        {
            isNeedVisitorsUpdate = false;
            if (this.modelControl.ModelContainer.ActiveCell == null)
                return;

            ModelPoint movePoint = this.modelControl.ScreenToModel(mouseMovePoint);
            ModelPoint prevMovePoint = this.modelControl.ScreenToModel(prevPoint);
            ModelPoint modelOffsetPoint = new ModelPoint(movePoint.X - prevMovePoint.X, movePoint.Y - prevMovePoint.Y);

            double value = modelOffsetPoint.X + modelOffsetPoint.Y;
            foreach (IComponent component in componentsForProcessing)
            {
                Shpross shpross = component as Shpross;
                shpross.SetLength(shpross.Length + value / 2, activeModelBoundingBox); 
            }

            prevPoint = mouseMovePoint;
            this.modelControl.ModelContainer.ActiveCell.Update();
        }

        public void EndExecute()
        {
            isNeedVisitorsUpdate = true;
            foreach (Shpross shpross in componentsForProcessing)
                this.endShprosses.Add(shpross.Copy() as Shpross);
        }

        public bool IsNeedModelUpdate
        {
            get { return true; }
        }

        public string Name
        {
            get { return "Изменить длину профиля"; }
        }

        #endregion

        #region ICloneable Members

        public object Clone()
        {
            CommandEditorChangeShprossLength clone = new CommandEditorChangeShprossLength(this.modelControl);
            clone.componentsForProcessing = new List<IComponent>(this.componentsForProcessing);

            foreach (Shpross startShpross in this.startShprosses)
                clone.startShprosses.Add(startShpross.Copy() as Shpross);

            foreach (Shpross endShpross in this.endShprosses)
                clone.endShprosses.Add(endShpross.Copy() as Shpross);

            clone.mouseDownPoint = this.mouseDownPoint;
            clone.mouseMovePoint = this.mouseMovePoint;
            clone.mouseUpPoint = this.mouseUpPoint;
            clone.mouseEvent = this.mouseEvent;
            clone.model = this.model;
            return clone;
        }

        #endregion

        #region ICommand Members


        public bool CanUndo
        {
            get { return true; }
        }

        public bool Undo(ModelControl modelControl)
        {
            
            for (int i = 0; i < this.startShprosses.Count; i++)
            {
                IComponent parent = modelControl.ModelContainer.GetParentComponentByComponentSerialNumber(this.startShprosses[i].SerialNumber);
                modelControl.ModelContainer.RemoveInnerComponentBySerialNumber(this.startShprosses[i].SerialNumber);
                parent.AddInnerComponent(this.startShprosses[i].Copy() as Shpross);
                //Shpross currentShpross = componentsForProcessing[i] as Shpross;
                //currentShpross.MoveStartPointTo(this.startShprosses[i].StartPoint);
                //currentShpross.MoveEndPointTo(this.startShprosses[i].EndPoint);
                //currentShpross.Height = this.startShprosses[i].Height;
            }
            return true;
        }

        public bool Redo(ModelControl modelControl)
        {
            for (int i = 0; i < this.endShprosses.Count; i++)
            {
                IComponent parent = modelControl.ModelContainer.GetParentComponentByComponentSerialNumber(this.endShprosses[i].SerialNumber);
                modelControl.ModelContainer.RemoveInnerComponentBySerialNumber(this.endShprosses[i].SerialNumber);
                parent.AddInnerComponent(this.endShprosses[i].Copy() as Shpross);

                //Shpross currentShpross = componentsForProcessing[i] as Shpross;
                //currentShpross.MoveStartPointTo(this.endShprosses[i].StartPoint);
                //currentShpross.MoveEndPointTo(this.endShprosses[i].EndPoint);
                //currentShpross.Height = this.endShprosses[i].Height;
            }
            return true;
        }

        #endregion

        public override string ToString()
        {
            return this.Name;
        }

        #region IModelComponentCommand Members

        private bool enabled = true;
        public bool Enabled
        {
            get
            {
                return enabled;
            }
            set
            {
                enabled = value;
            }
        }

        #endregion

        #region ICommand Members

        private bool isNeedVisitorsUpdate = true;
        public bool IsNeedVisitorsUpdate
        {
            get { return true; }
        }

        #endregion
    }
}
